#include<iostream>
#include<string>
#include<sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <ctime>
#include <openssl/sha.h>
#include<openssl/md5.h>
#include "sv_node.hpp"
#include "my570list.hpp"
#include "cs570.h"

extern char* HomeDir1;
extern char* LogFilename1;
extern int MyTimerFlag;

//-------------------------------------------------- Part2 Declarations Begin -------------------------------------//
unsigned int FileSizePrint;
FILE *fp6;
unsigned char* bitmap = new unsigned char[128];

//-------------------------------------------------- Part2 Declarations End --------------------------------------//



//----------------------------------------------------- Part2 Functions -----------------------------------------//


//--- Begin code borrowed from -- http://bytes.com/topic/c/answers/221005-convert-hex-string-decimal------------//
int hex_to_int(unsigned char hex[], int count)
{
int sum = 0;
int i;
int temp;

for (i = 0; i < count; i++)
{
temp = (hex[i] & 0xf0U) >> 4;
sum = sum*16 + temp;
temp = (hex[i] & 0x0fU);
sum = sum*16 + temp;
}
return sum;
}

//----- End code borrowed from -- http://bytes.com/topic/c/answers/221005-convert-hex-string-decimal------------//



unsigned char *GetSHA1(const char *filename)
{	   
	  
       unsigned char* results = (unsigned char*)malloc(20);
       struct stat st;
       SHA_CTX sha;
	   SHA1_Init(&sha);
       FILE *fp = fopen(filename,"r");
       stat(filename,&st);
       if(fp==NULL){
               cerr<<"File can not be opened; the program will terminate now."<<endl;
               exit(1);
       }
       
	   unsigned int fsize = st.st_size;
	   FileSizePrint = st.st_size;
	   unsigned int count = fsize/8192;

	   cout<<st.st_size<<endl;
	   //exit(1);

	   unsigned int actsize = fsize;

	   if(count>=1 && (fsize%8192)!=0){
		   count=count+1;
	   }else{
		   if(count==0){
			   count=1;
		   }else{
			   count=fsize/8192;
		   }
	   }

	   unsigned int buf_count =0;
	   for(unsigned int icount=0;icount<count;icount++){

		   if(actsize>=8192){
			   buf_count=8192;
		   }else{
			   buf_count=actsize;
		   }
		   actsize = actsize - 8192;

	   unsigned char* MsgBuf = (unsigned char*)malloc(8192);
	   memset(MsgBuf,0,8192);

	   size_t bytes_read;

	   bytes_read = fread(MsgBuf,1,buf_count,fp);
	   cout<<bytes_read<<endl;

	   SHA1_Update(&sha,MsgBuf,buf_count);
        
       buf_count=0;
	   free(MsgBuf);
	   }//count for loop
	   
      
       SHA1_Final(results,&sha);
       fclose(fp);
       for(int i=0;i<20;i++)
       {
               printf("%02x",results[i]);
       }
       cout<<endl;

     return results;

}



//----------------BITSET

void bitset(int bit)
{ 
   int byte=0;
   int bitposition =0;

   byte = bit/8;

   bitposition = bit%8;

   cout<<byte<<endl;
   cout<<bitposition<<endl;

     

   bitmap[127-byte] |=1 <<(bitposition);

  /* 
  for(int k=0;k<128;k++)
	{
	  printf("%02x",bitmap[k]);
	} 

	*/  
}



//----------------------------------------------------- Part2 Functions  End-----------------------------------------//


//FILE *Log;
struct timeval tim;
string LogLocation;

using namespace std;

//------------------------------------------------------ SIGNAL COMMIT----------------------------------//

pthread_t Keyboard_thread;
pthread_t KeepAlive_thread;

int newsock;

sigset_t sigalrm;
struct sigaction act;

sigset_t sigint;
struct sigaction act1;

sigset_t sigpipe;

int AutoShutDown;
ini_info *i1 = new ini_info();

void my_segment_handler(int sig)
{
	cerr<<"Insufficient program memory to execute Servant Node please restart the application"<<endl;
	exit(1);
}


void alrm(int sig)
{

	//cout<<"Signal SIGALRM received, the program will gracefully terminate now!"<<endl;

   AutoShutDown = 1;
   cout<<"servant:"<<i1->Port<<"> ";
   cout<<"Shutdown Triggered"<<endl;
   //cout<<thrd_count<<endl;
   pthread_kill(Keyboard_thread,SIGUSR1);
   pthread_kill(KeepAlive_thread,SIGUSR2);

}

void SignalHandler_sigusr1(int sig)
{
	//cout<<"Server defined signal for read/write/process clearance!"<<endl;
	//LocalShut=1;
	AutoShutDown=1;
	//close(mySocket);


}

void SignalHandler_sigusr2(int sig)
{
	//cout<<"KeepAlive thread woken up"<<endl;
}

void inte(int sig)
{
	//cout<<"INSIDE SIGINT MY FUNCTION"<<endl;
	//sleep(3);
	//MyTimerFlag=1;
	//exit(1);
	MyTimerFlag=1;
	cout<<endl;
}

//------------------------------------------------------------------------------------------------------//


//------------------------------------------------ GLOBAL VARIABLES BEGIN -----------------------------------------------//

int sockfd,newfd,len;
int activeconnection = 0;

int noofbeacons;
int yes = 1;
list<beacon>::iterator it;
int KeepAliveExit=0;
bool Duplicate = 1;
int KeepAliveTime=3;
int activeKeepAlive=0;
int dupGlobal = 1;
int counter = 1;
//FILE *status = NULL;
unsigned char *node_instance_id = new unsigned char[512];

//My570List *NeighborList = new My570List();
My570List* NeighborList = new My570List();
My570List* SocketList = new My570List();
//My570List* EventQ = new  My570List();

list<GlobalList_Elem*> GlobalList;// = new My570List();
pthread_attr_t attr;


//---------------------------------------- PTHREAD LOCKS AND CVS DECLARATIONS BEGIN------------------------------------//

pthread_cond_t EventQ_cv;

pthread_mutex_t NeighborList_lock; //= PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t SocketList_lock; //= PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t EventQ_lock; //= PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t GlobalList_lock;
pthread_mutex_t PrintLock;
pthread_mutex_t DBaseLock;
pthread_mutex_t status_lock;
pthread_mutex_t nam_lock;
pthread_mutex_t log_lock;
//---------------------------------------- PTHREAD LOCKS AND CVS DECLARATIONS END--------------------------------------//

char hostname[512];
unsigned char* UOIDstr = new unsigned char[20];
string extfile;

//------------------------------------------------ GLOBAL VARIABLES END -----------------------------------------------//


//------------------------------------------ KEEP ALIVE THREAD FUNCTION BEGIN -----------------------------------//

void *Keyboard_func(void* threadarg)
{

	signal(SIGUSR1,SignalHandler_sigusr1);

    //----------------------------------- SIGNALS AND AUTOSHUTDOWN ----------------------------------------- BEGIN//
	act1.sa_handler =inte;
	sigaction(SIGINT, &act1, NULL);
	pthread_sigmask(SIG_UNBLOCK, &sigint, NULL);
	//------------------------------------------------------------------------------------------------------ END//

	string s1="status";
	string s2="neighbors";
	string s3="files";
	string s4="shutdown";
	string s5="store";
	string temp,parse;

	int i=0;
	int ttl=0;


	int neighborsflag=0;
	int filesflag=0;
	int statusflag=0;
	int ShutDown=0;
	int storeflag=0;


	while(!AutoShutDown){
		statusflag=0;
//		cout<<"Inside Key Board Thread"<<endl;
		char* mystring = new char[256];
		temp.clear();
		parse.clear();
		cout<<"servant:"<<i1->Port<<"> ";
		gets(mystring);
		parse = string(mystring);
		//cout<<parse<<endl;
		i = parse.find_first_of(" ");
		temp=parse.substr(0,i);
		parse=parse.substr(i+1,parse.length()-i);
		if((s1.compare(temp)!=0) && (s4.compare(temp)!=0) && (s5.compare(temp)!=0))
		{
			//cout<<"servant:"<<i1->Port<<"> ";
			//cout<<"Malformed: Command not found"<<endl;
		}else{
			if(temp.compare("status")==0)
			{
				temp.clear();
				i=parse.find_first_of(" ");
                temp=parse.substr(0,i);
				if((temp.compare("neighbors")!=0) && (temp.compare("files")!=0)){
                   cout<<"servant:"<<i1->Port<<"> ";
			       cout<<"Malformed: Command not found"<<endl;
				}else{
					if(temp.compare("neighbors")==0){neighborsflag=1;}else{filesflag=1;continue;}
					parse=parse.substr(i+1,parse.length()-i);
					i=parse.find_first_of(" ");
					temp=parse.substr(0,i);
					ttl=atoi(temp.c_str());
					parse=parse.substr(i+1,parse.length()-i);
					extfile=parse;


				}
            statusflag=1;

			}// parse status here
			else
			{
				if(temp.compare("store")==0){
					storeflag=1;

					unsigned char* shaResults = new unsigned char[20] ;
					//SHA_CTX sKey;
					//SHA1_Init(&sKey);

					unsigned char* md5Results = new unsigned char[16] ;
					//MD5_CTX mKey;
					//MD5_Init(&mKey);

					string LocalFile;
					string temp1;
					string temp2;
					string temp3;
					string temp4;
					string NodeHome;
					string FilesHome;
					string FilesRef;
					string FileName;
					string MetaName;
					char myCurrName[100];
					char myFileName[100];
					char ch;
					string metaNames;

					int LocalIter=0;
					int LocalTtl=0;
					int j=0;
					int k=0;
					int l=0;
					int bitraise=0;
					int actualbit=0;
					int checkbit=0;

					temp.clear();
					while(1){
						cout<<"inside while"<<endl;
						cout<<parse<<"*"<<endl;
						if(LocalIter==2){
                           metaNames=parse;
						  // cout<<metaNames<<"MMMMMMMMMMMMMMMMMMMM"<<endl; exit(1);
						}
						LocalIter=LocalIter+1;

					i=parse.find_first_of(" ");
					// parse holds everything from store
					if(i==-1){

                          goto jump;    

						  /*cout<<"Inside i=-1 and temp = "<<temp<<endl;
                          temp1.clear();
						  temp2.clear();
						  j=parse.find_first_of("=");
						  temp1=parse.substr(0,j);
						  temp2=parse.substr(j+1,temp.length()-j-1);

						  cout<<"+++key"<<temp1<<endl;
						  cout<<"+++key"<<temp2<<endl;

						  //exit(1);

						break;*/
					}

					temp=parse.substr(0,i);
					parse=parse.substr(i+1,parse.length()-i);

					if(LocalIter ==1)
						{
						  LocalFile = temp;
						  FILE *fp1= fopen(LocalFile.c_str(),"rb");
						  if(fp1==NULL){
							  cerr<<"File can not be openend please try again"<<endl;
							  continue;
						  }else{
							  // create files sub direcroy

							  NodeHome = (string(HomeDir1)).substr(0,(int)strlen(HomeDir1)-1);
							  FilesHome = NodeHome + "/files";

                              struct stat mystat;
							  if(stat(FilesHome.c_str(),&mystat) == 0){
								  FilesRef= FilesHome + "/FilesRef";
								  cout<<"directory is present"<<endl;
							  }else{
								  int zero;
								  zero=0;
								  mkdir(FilesHome.c_str(),00777);
								  FilesRef= FilesHome + "/FilesRef";
								  FILE *fp2 = fopen(FilesRef.c_str(),"w");
								  fprintf(fp2,"%d",zero);
								  fclose(fp2);

								  cout<<"Directory created"<<endl; 
							  }
							
						  }
						  cout<<FilesRef.c_str()<<endl;
                              
                          FILE *fp3 = fopen(FilesRef.c_str(),"r");
						  fgets(myFileName,100,fp3);
						  
						  k=atoi(myFileName);
						  sprintf(myCurrName,"%d",k+1);
						  FileName = FilesHome +"/"+string(myCurrName) +".data";
						  MetaName = FilesHome +"/"+string(myCurrName) +".meta";

						  remove(FilesRef.c_str());
						  

                          cout<<k+1;
						  //exit(1);
						  FILE *fp4 = fopen(FilesRef.c_str(),"w");
						  fprintf(fp4,"%d",k+1);
						  fclose(fp4);

						  FILE *fp5 = fopen(FileName.c_str(),"wb");

						  while(!feof(fp1)){
							  ch = fgetc(fp1);
							  if(!feof(fp1))
                              fputc(ch,fp5);

						  }// while fp1

						  fclose(fp1);
						  fclose(fp5);

						  fp6 = fopen(MetaName.c_str(),"w");
						  fprintf(fp6,"[metadata]\n");
						  fprintf(fp6,"FileName=%s\n",LocalFile.c_str());
						  
						  unsigned char* mySha = new unsigned char[20];
						  memcpy(mySha,GetSHA1(LocalFile.c_str()),20);

                          fprintf(fp6,"FileSize=%u\n",FileSizePrint); 
						  fprintf(fp6,"SHA1=");
						  for(int i=0;i<20;i++)
                          {
                           fprintf(fp6,"%02x",mySha[i]);
                          }
						  fprintf(fp6,"\n");
						  unsigned char* myUD = new unsigned char[20];
						  myUD = GetUOID(node_instance_id,"file");
                          fprintf(fp6,"NONCE=");
						  for(int i1=0;i1<20;i1++)
						  {
                           fprintf(fp6,"%02x",myUD[i1]); 
						  }
						  fprintf(fp6,"\n");
						  fprintf(fp6,"Keywords=");
						 // fclose(fp6);

						}// LocalIter ==1
                    if(LocalIter ==2)
						{
						  LocalTtl = atoi(temp.c_str());
						  cout<<LocalTtl<<"::::"<<endl;
						}

                    if(LocalIter >2)
						{
						jump:
							{
						  temp1.clear();
						  temp2.clear();
						  temp3.clear();
						  temp4.clear();

						  j=metaNames.find_first_of("=");
						  if(j==-1){
							  break;
						  }
						  temp1=metaNames.substr(0,j);
						  actualbit=0;
						  bitraise=0;
						  checkbit=0;
						  cout<<"temp1 "<<temp1<<endl;
						  fprintf(fp6,"%s ",temp1.c_str());
						  //SHA1_Update(&sKey,temp1.c_str(),temp1.length());
						  SHA1((const unsigned char*)temp1.c_str(),temp1.length(),shaResults);
						  bitraise = hex_to_int((unsigned char*)&shaResults[18],1);
								  checkbit=(bitraise&1);
								  if(checkbit==1){
									  actualbit=256+512;
								  }else{
									  actualbit=512;
								  }
								  bitraise = hex_to_int((unsigned char*)&shaResults[19],1);
								  cout<<"bitraise temp1 sha1"<<bitraise<<endl;
								  actualbit=actualbit+bitraise;
								  cout<<"++temp abit "<<actualbit<<endl;
								  bitset(actualbit);

                          actualbit=0;
						  bitraise=0;
						  checkbit=0;
						  
						  MD5((const unsigned char*)temp1.c_str(),temp1.length(),md5Results);				
						  bitraise = hex_to_int((unsigned char*)&md5Results[14],1);
								  checkbit = (bitraise&1);
								  
								  if(checkbit==1){
									  actualbit=256;
								  }else{
									  actualbit=0;
								  }
								  bitraise = hex_to_int((unsigned char*)&md5Results[15],1);
								  cout<<"bitraise temp1 md5"<<bitraise<<endl;
								  actualbit = actualbit+bitraise;
								  cout<<"++temp abit "<<actualbit<<endl;
								  bitset(actualbit);
						  //MD5_Update(&mKey,temp1.c_str(),temp1.length());

						  metaNames = metaNames.substr(j+1,metaNames.length()-j-1);
						  l=metaNames.find_first_of("\"");
						  metaNames=metaNames.substr(l+1,metaNames.length()-l-1);
						  l=metaNames.find_first_of("\"");
						  temp3=metaNames.substr(0,l);
						  metaNames=metaNames.substr(l+1,metaNames.length()-l-1);

						  while(temp3.length()!=0)
							{
							  j=temp3.find_first_of(" ");

							  if(j==-1){
								  actualbit=0;
								  bitraise=0;
								  checkbit=0;
								  cout<<"++keyt3 "<<temp3<<endl;
								  fprintf(fp6,"%s ",temp3.c_str());
								  //SHA1_Update(&sKey,temp3.c_str(),temp3.length());
								  //MD5_Update(&mKey,temp3.c_str(),temp3.length());
								  SHA1((const unsigned char*)temp3.c_str(),temp3.length(),shaResults);
								  bitraise = hex_to_int((unsigned char*)&shaResults[18],1);
								  checkbit=(bitraise&1);
								  if(checkbit==1){
									  actualbit=256+512;
								  }else{
									  actualbit=512;
								  }
								  bitraise = hex_to_int((unsigned char*)&shaResults[19],1);
								  actualbit=actualbit+bitraise;
								  cout<<"++keyt3 abit "<<actualbit<<endl;
                                  bitset(actualbit);

								  actualbit=0;
								  bitraise=0;
								  checkbit=0;

						          MD5((const unsigned char*)temp3.c_str(),temp3.length(),md5Results);
								  bitraise = hex_to_int((unsigned char*)&md5Results[14],1);
								  checkbit = (bitraise&1);
								  
								  if(checkbit==1){
									  actualbit=256;
								  }else{
									  actualbit=0;
								  }
								  bitraise = hex_to_int((unsigned char*)&md5Results[15],1);
								  actualbit = actualbit+bitraise;
								  cout<<"++keyt3 abit "<<actualbit<<endl;
								  bitset(actualbit);

								  temp3.clear();
								  
							  }else{

								  actualbit=0;
								  bitraise=0;
								  checkbit=0;

                                  temp4=temp3.substr(0,j);
								  temp3=temp3.substr(j+1,temp3.length()-j-1);
								  cout<<"++keyt4 "<<temp4<<endl;                                                                    
								  fprintf(fp6,"%s ",temp4.c_str());

								  SHA1((const unsigned char*)temp4.c_str(),temp4.length(),shaResults);
								  bitraise = hex_to_int((unsigned char*)&shaResults[18],1);
								  checkbit=(bitraise&1);
								  if(checkbit==1){
									  actualbit=256+512;
								  }else{
									  actualbit=512;
								  }
								  bitraise = hex_to_int((unsigned char*)&shaResults[19],1);
								  actualbit=actualbit+bitraise;
								  cout<<"++keyt4 abit "<<actualbit<<endl;
								  bitset(actualbit);

								  actualbit=0;
								  bitraise=0;
								  checkbit=0;

						          MD5((const unsigned char*)temp4.c_str(),temp4.length(),md5Results);

								  bitraise = hex_to_int((unsigned char*)&md5Results[14],1);
								  checkbit = (bitraise&1);
								  
								  if(checkbit==1){
									  actualbit=256;
								  }else{
									  actualbit=0;
								  }
								  bitraise = hex_to_int((unsigned char*)&md5Results[15],1);
								  actualbit = actualbit+bitraise;
								  cout<<"++keyt4 abit "<<actualbit<<endl;
                                  bitset(actualbit); 
								  temp4.clear();
							  }
							}
						  i=metaNames.find_first_of(" ");
						  if(i==-1){
							  break;
							  }else{
								  parse=metaNames.substr(i+1,metaNames.length()-i-1);
								  metaNames=parse;
							  }
						  cout<<"metaNames"<<metaNames<<endl;
						 
							}//jump
						}

			      	}//while loop
              fprintf(fp6,"\n");
			  fprintf(fp6,"Bit-vector= \n");
			  for(int k=0;k<128;k++)
				{
				  fprintf(fp6,"%02x",bitmap[k]);
				}
              fprintf(fp6,"\n\n");     
              fclose(fp6);
		//	  exit(1);//store exit ---------------------------- please comment it later--//

				}//if store
				//cout<<"inside shutdown"<<endl;
								if(temp.compare("shutdown")==0){

				ShutDown=1;
								}
				//alarm(1);
				//break;
			}//else

		}

		if(ShutDown==1){
			//SENDING NOTIFY

			Flood_Elem* fd_obj = new Flood_Elem();
		fd_obj->Port = i1->Port;
		fd_obj->MessageType = NTFY;
		fd_obj->UOID = new unsigned char[20];
		fd_obj->TTL = (unsigned char)1;

		memcpy(fd_obj->UOID,GetUOID(node_instance_id,"msg"),20);

		GlobalList_Elem *Gelem = new GlobalList_Elem();
		Gelem->UOID = new unsigned char[20];

		//Gelem->ListP = *EventQ;
		Gelem->Port =  fd_obj->Port;
		Gelem->Temp = 5;
		//Gelem->Socket=mySocket;
		memcpy(Gelem->UOID,fd_obj->UOID,20);

		/////

		list<GlobalList_Elem*>::iterator it;
	 pthread_mutex_lock(&GlobalList_lock);
	 for (it =GlobalList.begin();it!=GlobalList.end();it++ )
	 {
			   GlobalList_Elem *g1 = NULL;
			   g1 = (GlobalList_Elem*) (*it);
			   if ((*it)!=NULL)
			   {
					   if (g1->Temp != 1 && g1->Temp!=2 &&g1->Temp!=4)
					   {
					   //cout<<"Keyboard Flooding1 to "<<g1->Port<<endl;
					   pthread_mutex_lock(&g1->EventQlock);
					   (g1->ListP).push_back(fd_obj);
					   pthread_mutex_unlock(&g1->EventQlock);
					   pthread_cond_broadcast(&g1->EventQ_cv);
					   }
			   }

	 }
	 pthread_mutex_unlock(&GlobalList_lock);
            sleep(2);
			alarm(1);
			sleep(3);
		}//sending notify end of if shutdown=1

		if(AutoShutDown==1){break;}

		if(statusflag==1){
		//cout<<"Parsing done"<<endl;
		//cout<<"ttl "<<ttl<<endl;
		//cout<<"extfile "<<extfile<<endl;

		pthread_mutex_lock(&GlobalList_lock);
		//if(GlobalList.size()==0)
		//	{
			 FILE* status = fopen(extfile.c_str(),"w");
			 if(status == NULL){
				cerr<<"Status file can not be generated. Please try again!"<<endl;
				pthread_mutex_unlock(&GlobalList_lock);
				continue;
				}else{
					 fprintf(status,"V -t * -v 1.0a5\n");
					 fprintf(status,"n -t * -s %u -c red -i black\n",(unsigned short)(i1->Port));
					 fclose(status);//continue;

				 }

		//	}
		pthread_mutex_unlock(&GlobalList_lock);

        //status = fopen(extfile.c_str(),"w");
		//if(status == NULL){cerr<<"Status file can not be generated. Please try again!"<<endl; continue;}

		//pthread_mutex_lock(&status_lock);
		//fprintf(status,"V -t * -v 1.0a5\n");
		//fclose(status);
		//pthread_mutex_unlock(&status_lock);

		Flood_Elem* fd_obj = new Flood_Elem();
		fd_obj->Port = i1->Port;
		fd_obj->MessageType = STRQ;
		fd_obj->UOID = new unsigned char[20];
		fd_obj->TTL = (unsigned char)ttl;

		memcpy(fd_obj->UOID,GetUOID(node_instance_id,"msg"),20);

		GlobalList_Elem *Gelem = new GlobalList_Elem();
		Gelem->UOID = new unsigned char[20];

		//Gelem->ListP = *EventQ;
		Gelem->Port =  fd_obj->Port;
		Gelem->Temp = 2;
		//Gelem->Socket=mySocket;
		memcpy(Gelem->UOID,fd_obj->UOID,20);

		pthread_mutex_lock(&GlobalList_lock);
		GlobalList.push_back(Gelem);
		dupGlobal = eval_Global();
		pthread_mutex_unlock(&GlobalList_lock);
		//cout<<"Object Populated"<<endl;
		//print_GlobalList();
        //int thrd_Keyboard_read=0;
		//int thrd_Keyboard_write=0;
		//pthread_t Keyboard_read;
		//pthread_t Keyboard_write;

        if(ttl!=0){

        if(GlobalList.size()==0){
	     cout<<"servant:"<<i1->Port<<"> ";cout<<"No neighbors are connected yet, please try again for status!"<<endl;
		 usleep(500);
		 continue;
		}

		//--------------------------------PLACING IT INTO ALL NEIGHBOR EVENT Qs ----------BEGIN//
			//pthread_mutex_lock(&PrintLock);
	//		print_GlobalList();
			//pthread_mutex_unlock(&PrintLock);
			//exit(1);
		 list<GlobalList_Elem*>::iterator it;
		 pthread_mutex_lock(&GlobalList_lock);
		 for (it =GlobalList.begin();it!=GlobalList.end();it++ )
		 {
				   GlobalList_Elem *g1 = NULL;
				   g1 = (GlobalList_Elem*) (*it);
				   if ((*it)!=NULL)
				   {
						   if (g1->Temp != 1 && g1->Temp!=2)
						   {
						  // cout<<"Keyboard Flooding to "<<g1->Port<<endl;
						   pthread_mutex_lock(&g1->EventQlock);
						   (g1->ListP).push_back(fd_obj);
						   pthread_mutex_unlock(&g1->EventQlock);
						   pthread_cond_broadcast(&g1->EventQ_cv);
						   }
				   }

		 }
		 pthread_mutex_unlock(&GlobalList_lock);
		// cout<<"Object placed into the event q"<<endl;
		}else{
		//	cout<<"TTL IS ZERO"<<endl;
		}

        int mysleep=0;
		if(i1->MsgLifetime==0){
			mysleep = 30;
		}else{
			mysleep = i1->MsgLifetime;
		}
        sleep(mysleep);
     	//cout<<"//--------------------------------PLACING IT INTO ALL NEIGHBOR EVENT Qs ----------END//"<<endl;








		//--------------------------------- STATUS MESSAGE FORMATION ---------------------BEGIN//

		/*struct HEADER sHeader;

		sHeader.MessageType = STRQ;
        sHeader.UOID = new unsigned char[20];
		for(int it2=0;it2<20;it2++){
					sHeader.UOID[it2]=UOIDstr[it2];
				}

		sHeader.TTL = (unsigned char)ttl;
		sHeader.Reserved = (unsigned char)0;
		sHeader.DataLength = 1;

		struct STATUS_MSG sMsg;

		if(neighborsflag==1){sMsg.StatusTyp=neighbors;}else{sMsg.StatusType=files;}

		unsigned char* StatusMsg = new unsigned char[512];
		memcpy(&StatusMsg[0],&sHeader.MessageType,1);
		memcpy(&StatusMsg[1],sHeader.UOID,20);
		memcpy(&StatusMsg[21],&sHeader.TTL,1);
		memcpy(&StatusMsg[22],&sHeader.Reserved,1);
		memcpy(&StatusMsg[23],&sHeader.DataLength,4);
		memcpy(&StatusMsg[27],&sMsg.StatusType,1); */

		//--------------------------------- STATUS MESSAGE FORMATION ---------------------END//



		}// if statusflag==1




	}//while

	//cout<<"broken from keyboard"<<endl;
	/////


    close(sockfd);
	close(newsock);

	pthread_exit(NULL);
}
/*
void pipe(int sig)
{
	int x;
	cout<<"Caught sigpipe waiting on user to react"<<endl;
	cin>>x;
	pthread_mutex_unlock(&NeighborList_lock);
	pthread_mutex_lock(&NeighborList_lock);
	if(NeighborList->Length()!=0 && activeKeepAlive==1)
	{
		NeighborList->Unlink(NeighborList->First());
	}
	pthread_mutex_unlock(&NeighborList_lock);
}
*/
void *KeepAlive_func(void*)
{

	signal(SIGUSR2,SignalHandler_sigusr2);
	//list<NeighborList_Elem>::iterator hmi;
/*	act.sa_handler =pipe;
	sigaction(SIGPIPE, &act, NULL);
	pthread_sigmask(SIG_UNBLOCK, &sigpipe, NULL);*/


	//cout<<"Inside KeepAlive "<<endl;
	while(!AutoShutDown)
	{
		sleep(i1->KeepAliveTimeout);

		Flood_Elem* fd_obj = new Flood_Elem();
		fd_obj->Port = i1->Port;
		fd_obj->MessageType = KPAV;
		fd_obj->UOID = new unsigned char[20];
		fd_obj->TTL = (unsigned char)1;

		memcpy(fd_obj->UOID,GetUOID(node_instance_id,"msg"),20);

		GlobalList_Elem *Gelem = new GlobalList_Elem();
		Gelem->UOID = new unsigned char[20];

		//Gelem->ListP = *EventQ;
		Gelem->Port =  fd_obj->Port;
		Gelem->Temp = 4;
		//Gelem->Socket=mySocket;
		memcpy(Gelem->UOID,fd_obj->UOID,20);

//		pthread_mutex_lock(&GlobalList_lock);
//		GlobalList.push_back(Gelem);
//		dupGlobal = eval_Global();
//		pthread_mutex_unlock(&GlobalList_lock);


	 list<GlobalList_Elem*>::iterator it;
	 pthread_mutex_lock(&GlobalList_lock);
	 for (it =GlobalList.begin();it!=GlobalList.end();it++ )
	 {
			   GlobalList_Elem *g1 = NULL;
			   g1 = (GlobalList_Elem*) (*it);
			   if ((*it)!=NULL)
			   {
					   if (g1->Temp != 1 && g1->Temp!=2)
					   {
					//   cout<<"Keyboard Flooding1 to "<<g1->Port<<endl;
					   pthread_mutex_lock(&g1->EventQlock);
					   (g1->ListP).push_back(fd_obj);
					   pthread_mutex_unlock(&g1->EventQlock);
					   pthread_cond_broadcast(&g1->EventQ_cv);
					   }
			   }

	 }
	 pthread_mutex_unlock(&GlobalList_lock);

	}
   pthread_exit(NULL);
}

//------------------------------------------ KEEP ALIVE THREAD FUNCTION END -------------------------------------//


//----------------------------------------- BEACON CONNECT THREAD BEGIN -----------------------------------------//
void *beaconconnectthread(void *threadarg)
{
	int ret;
	pthread_t readt,writet;
	for (it=i1->BeaconList.begin(); it!=i1->BeaconList.end(); it++)
	{
		if(AutoShutDown==1){break;}
		while(!AutoShutDown){

			 newsock=0;

			struct sockaddr_in serv_addr;

			//---------------------------------  CREATING THE SOCKET TO CONNECT TO OTHER BEACONS ----------------//
			newsock = socket(AF_INET,SOCK_STREAM,0);
			if (newsock < 0)
			{
			//	perror("Socket");
				exit(1);
			}
			memset(&serv_addr,0,sizeof (serv_addr));
			serv_addr.sin_family = AF_INET;
			serv_addr.sin_port = htons((*it).BeaconPort);
			if (serv_addr.sin_port == i1->Port)
			{
				close(newsock);
				break;
			}
			if (connect(newsock, (struct sockaddr *)&serv_addr,sizeof(serv_addr))<0)
			{
				usleep(100);
				close(newsock);
			}else{
				int dupli=0;
				activeconnection = 1;
				//cout<<"Connected to "<<serv_addr.sin_port<<endl;

				struct sockaddr_in sa;
				int sock_len;
				sock_len = sizeof(sa);
				getsockname(newsock,(struct sockaddr *)&sa,(socklen_t *)&sock_len);

				//////CREATE HELLO PACKET/////
				struct HEADER hello;
				struct HELLO_MSG msg;

				hello.UOID = new unsigned char[20];
				hello.MessageType=HLLO;
				for(int it2=0;it2<20;it2++){
					hello.UOID[it2]=(GetUOID(node_instance_id,"msg"))[it2];
	//					printf("%02x",(unsigned char)UOIDstr[it2]);
				}
				//cout<<endl;

				int i=30;
				if(i1->TTL==0){hello.TTL=(unsigned char)i;}else{hello.TTL=(unsigned char)i1->TTL;}

				hello.Reserved=(unsigned char)0;
                msg.HostPort=i1->Port;
				msg.HostName=hostname;
				hello.DataLength=(int)strlen(msg.HostName)+2;//intLength((int)msg.HostPort);

				unsigned char* HelloMessage = new unsigned char[512];
				memset(HelloMessage,'\0',512);
				memcpy(&HelloMessage[0],&hello.MessageType,1);
                memcpy(&HelloMessage[1],hello.UOID,20);
				memcpy(&HelloMessage[21],&hello.TTL,1);
				memcpy(&HelloMessage[22],&hello.Reserved,1);
				memcpy(&HelloMessage[23],&hello.DataLength,4);
				memcpy(&HelloMessage[27],&msg.HostPort,2);
				memcpy(&HelloMessage[29],&msg.HostName,strlen(msg.HostName));

	//			cout<<"Host port being sent from connect "<<msg.HostPort<<endl;
				/////////////////////////// END HELLO PACKET CREATION//////////////


					//---------------------------- SENDING HELLO MESSAGE FROM THE CONNECT THREAD BEGIN ---------------------------//
					for (unsigned int it4 = 0;it4<27 ;it4++ )
					{
						if (send(newsock,&HelloMessage[it4],1,0)==-1)
						{
							//perror("beaconconnect1: write");
							exit(1);
						}

					}
					for (unsigned int it5 = 27;it5<27+hello.DataLength; it5++ )
					{
						if (send(newsock,&HelloMessage[it5],1,0)==-1)
						{
						//	perror("beaconconnect2: write");
							exit(1);
						}

					}
				//	cout<<"SENT MESSAGE from "<<(int) ntohs(sa.sin_port)<<" to "<<serv_addr.sin_port<<endl;
				//	cout<<"UUUUUUUUUUUUUUUUOOOOOOOOOOOOOOOOOOOOIIIIIIIIIIIIIIIIIIIIIIIIIDDDDDDDDDDDDDDDDDDDDDD"<<endl;
					for(int it2=0;it2<20;it2++){
	//					printf("%02x",(unsigned char)hello.UOID[it2]);
					}

						//---------------------------------------------- RESET----------------------------------------------------//
					pthread_mutex_lock(&log_lock);
					FILE *Log = fopen(LogLocation.c_str(),"a");
					if(Log==NULL)
					{
						cerr<<"Log file can not be opened. The program will continue without logging."<<endl;
					}else{
						if (serv_addr.sin_port != i1->Port)
						{
							gettimeofday(&tim,NULL);
							fprintf(Log,"s %10ld.%03d nunki.usc.edu_%d HLLO %d ",(tim.tv_sec),(int)((tim.tv_usec)/1000),serv_addr.sin_port,(int)(hello.TTL));
							for(int pr=16;pr<20;pr++){fprintf(Log,"%02x",hello.UOID[pr]);}
							fprintf(Log," %d nunki.usc.edu\n",msg.HostPort);
							fflush(Log);
						}
					}
					fclose(Log);
					pthread_mutex_unlock(&log_lock);

					//---------------------------------------------------------------------------------------------------------//
/*
					//------------------------------ APPENDING NEIGHBORS FOR KEEPALIVE BEGIN -------------------------------------//

					//ACQUIRE A LOCK ON THE NEIGHBOR LIST AND APPEND THE NEIGHBOR INTO THE LIST
					pthread_mutex_lock(&NeighborList_lock);
                    NeighborList.push_back(elem);
                    pthread_mutex_unlock(&NeighborList_lock);
					//------------------------------ APPENDING NEIGHBORS FOR KEEPALIVE END ---------------------------------------//
*/					//---------------------------- SENDING HELLO MESSAGE FROM THE CONNECT THREAD END -----------------------------//


					//---------------------------- RECEIVING HELLO MESSAGE RESPONSE BEGIN ----------------------------------------//

					unsigned char * HelloReceived = new unsigned char[512];
					struct HEADER helloRecvd;
					struct HELLO_MSG RecvdMsg;

					memset(&helloRecvd,0,sizeof helloRecvd);

					int numbytes;
					for (unsigned int it6 = 0;it6<27 ;it6++ )
					{
						if ((numbytes = read(newsock, &HelloReceived[it6], 1))<0)
						{
						//	perror("read1");
							break;
							//exit(1);
						}
					}
					if (serv_addr.sin_port == i1->Port)
					{
						close(newsock);
						break;
					}
					pthread_mutex_lock(&GlobalList_lock);
					list<GlobalList_Elem*>::iterator globalit;
					for (globalit = GlobalList.begin();globalit!=GlobalList.end();globalit++)
					{
						GlobalList_Elem* g1 = new GlobalList_Elem();
						g1 = (GlobalList_Elem*) (*globalit);
						if (g1->Port == serv_addr.sin_port)
						{
							//cout<<"Duplicate connection: "<<g1->Port<<endl;
						//	GlobalList.remove(*globalit);
							close(newsock);
							dupli = 1;
						}
					}
					pthread_mutex_unlock(&GlobalList_lock);

					if (numbytes == 0 || dupli == 1)
					{
						//cout<<"Here"<<endl;
						close(newsock);
						break;
					}
					else{

					helloRecvd.UOID = new unsigned char[20];

					//---------------------------- RECEIVING HELLO MESSAGE RESPONSE END ----------------------------------------//
					memcpy(&helloRecvd.MessageType,&HelloReceived[0],1);
					memcpy(helloRecvd.UOID,&HelloReceived[1],20);
					memcpy(&helloRecvd.TTL,&HelloReceived[21],1);
					memcpy(&helloRecvd.Reserved,&HelloReceived[22],1);
					memcpy(&helloRecvd.DataLength,&HelloReceived[23],4);
/*					for(int it2=0;it2<20;it2++){
						printf("%02x",(unsigned char)helloRecvd.UOID[it2]);
					}
					cout<<endl;
*/					for (unsigned int it3 = 27;it3<27+helloRecvd.DataLength ;it3++ )
					{
						if ((numbytes = read(newsock, &HelloReceived[it3], 1))==-1)
						{
							//perror("read2");
						}
					}
					memcpy(&RecvdMsg.HostPort,&HelloReceived[27],2);
					memcpy(&RecvdMsg.HostName,&HelloReceived[29],helloRecvd.DataLength-2);

					//cout<<"UUUUUUUUUUUUUUUUOOOOOOOOOOOOOOOOOOOOIIIIIIIIIIIIIIIIIIIIIIIIIDDDDDDDDDDDDDDDDDDDDDD"<<endl;
					for(int it2=0;it2<20;it2++){
	//					printf("%02x",(unsigned char)helloRecvd.UOID[it2]);
					}

					//---------------------------------------------- RESET----------------------------------------------------//
					pthread_mutex_lock(&log_lock);
					FILE *Log = fopen(LogLocation.c_str(),"a");
					if(Log==NULL)
					{
						cerr<<"Log file can not be opened. The program will continue without logging."<<endl;
					}else{
					if (serv_addr.sin_port != i1->Port)
					{
					gettimeofday(&tim,NULL);
					fprintf(Log,"r %10ld.%03d nunki.usc.edu_%d HLLO %d ",(tim.tv_sec),(int)((tim.tv_usec)/1000),RecvdMsg.HostPort,(int)(helloRecvd.TTL));
						for(int pr=16;pr<20;pr++){fprintf(Log,"%02x",helloRecvd.UOID[pr]);}
					fprintf(Log," %d nunki.usc.edu\n",RecvdMsg.HostPort);
					fflush(Log);
					}
					}
					fclose(Log);
					pthread_mutex_unlock(&log_lock);
					//---------------------------------------------------------------------------------------------------------//

					//----------------------------------------------- BUILD ELEM FOR NEIGHBOR LIST -------------------------------//

						NeighborList_Elem* elem1 = new NeighborList_Elem();
						elem1->UOID = new unsigned char[20];
						memcpy(elem1->UOID,&HelloReceived[1],20);
						memcpy(&(elem1->HostPort),&HelloReceived[27],2);

					// Loop Test Print/UOID  for(int it2=0;it2<20;it2++){printf("%02x",(unsigned char)(elem1->UOID)[it2]);}cout<<endl;cout<<elem1->HostPort<<endl;exit(1);

					//----------------------------------------------BUILD ELEM FOR NEIGHBOR LIST END TESTED CHECKED-----------------------------//

					//ACQUIRE A LOCK ON THE NEIGHBOR LIST AND APPEND THE NEIGHBOR INTO THE LIST
					pthread_mutex_lock(&NeighborList_lock);
//					for(int it2=0;it2<20;it2++){printf("%02x",(unsigned char)(elem1->UOID)[it2]);}cout<<endl;cout<<elem1->HostPort<<endl;
					NeighborList->Append((void *)elem1);
					Duplicate = eval_Duplicate();
					//print_NeighborList();
					if (Duplicate == 0)
					{
					//	cout<<"Duplicate found on beaconconnect"<<endl;
					}
					pthread_mutex_unlock(&NeighborList_lock);
					//------------------------------ APPENDING NEIGHBORS FOR DUPLICATES END ---------------------------------------//

					pthread_mutex_lock(&SocketList_lock);
					SocketList->Append((void*)newsock);
					pthread_mutex_unlock(&SocketList_lock);
					//------------------------------ APPENDING TO GLOBAL LIST ----------------------------------------------------//

					//My570List *EventQ = new My570List();
					list<Flood_Elem*>* EventQ = new list<Flood_Elem*>;
					GlobalList_Elem *Gelem = new GlobalList_Elem();
					Gelem->UOID = new unsigned char[20];
					Gelem->ListP = *EventQ;
					Gelem->Port =  RecvdMsg.HostPort;
					Gelem->Temp = 0;
					Gelem->Socket=newsock;
					memcpy(Gelem->UOID,&HelloReceived[1],20);

					//cout<<"Putting "<<Gelem->Port<<" into Global list"<<endl;
					pthread_mutex_lock(&GlobalList_lock);
					GlobalList.push_back(Gelem);
					dupGlobal = eval_Global1();
	//				print_GlobalList();
					pthread_mutex_unlock(&GlobalList_lock);

					//------------------------------ APPENDING TO GLOBAL LIST ----------------------------------------------------//
					//cout<<"newsock1 "<<newsock<<" connected to "<<RecvdMsg.HostPort<<endl;

					if ((ret = pthread_create(&readt,NULL,readthread,(void *)Gelem)))
					{
						//error has occurred
						fprintf(stderr,"Error:pthread_create, %s\n",strerror(ret));
						exit(1);
					}
					//cout<<"newsock2 "<<newsock<<" connected to "<<RecvdMsg.HostPort<<endl;

					if ((ret = pthread_create(&writet,NULL,writethread,(void *)Gelem)))
					{
						//error has occurred
						fprintf(stderr,"Error:pthread_create, %s\n",strerror(ret));
						exit(1);
					}

					//cout<<"Connected to "<<serv_addr.sin_port<<endl;

					break;

					}//end else condition numbytes =0
				}//end else connect
			}//end while
		//}//end else same port
	}//end for
	//cout<<"break beacon connect"<<endl;
	return 0;

}
void *serverthread(void *threadarg)
{
	//------------------------------------------//
	act.sa_handler =alrm;
	sigaction(SIGALRM, &act, NULL);
	pthread_sigmask(SIG_UNBLOCK, &sigalrm, NULL);


	//--------------------------------signals---//
	int ret;
	pthread_t readt,writet;
	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
                sizeof(int)) == -1) {
         //   perror("setsockopt");
            exit(1);
        }
	struct sockaddr_in serv_addr;
	struct sockaddr_in cli_addr; // connector's address information
	socklen_t sin_size = 0;
	sin_size = sizeof(cli_addr);
	memset(&serv_addr,0,sizeof (struct sockaddr_in));//serv_addr.sin_zero);
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(i1->Port);
	//cout<<"before bind sockfd: "<<(int)threadarg<<endl;
	if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
	{
		//perror("bind");
		exit(1);
	}else {
		//cout<<"Bound to socket "<<sockfd<<endl;//exit(1);
	}
	if (listen(sockfd, 10) == -1)
	{
		//perror("listen");
		exit(1);
	}
	while (!AutoShutDown)
	{
		int checkFlag=0;
		//cout<<"Waiting on accept: Port: "<<i1->Port<<endl;
		newfd = accept(sockfd, (struct sockaddr *)&cli_addr, &sin_size);
		if (newfd == -1) {

//            perror("accept");
            usleep(100);

        }else {
		//	cout<<"I have accepted on port "<<serv_addr.sin_port<<" socket "<<sockfd<<endl;
			socklen_t len;
			struct sockaddr_in peer;
			len = sizeof peer;
			getpeername(newfd, (struct sockaddr*)&peer, &len);
		//	cout<<"peer port number "<<ntohs(peer.sin_port)<<endl;
			int numbytes;
		//	cout<<"About to read from "<<ntohs(peer.sin_port)<<endl;
			unsigned char * HelloReceived1 = new unsigned char[512];
			list<GlobalList_Elem*>::iterator globalit;
			for (globalit = GlobalList.begin();globalit!=GlobalList.end();globalit++)
			{
				GlobalList_Elem* g1 = new GlobalList_Elem();
				g1 = (GlobalList_Elem*) (*globalit);
				if (g1->Temp == 1)
				{
		//			cout<<"Temp connection: "<<g1->Port<<endl;
					GlobalList.remove(*globalit);
				}
			}
			//------------------------------HEADER FOR RECEIVING----------------------------------------------//
			struct HEADER helloRecvd1;
			memset(&helloRecvd1,0,sizeof helloRecvd1);
			struct HELLO_MSG RecvdMsg1;
			memset(&RecvdMsg1,0, sizeof RecvdMsg1);
			//------------------------------HEADER FOR RECEIVING END----------------------------------------------//

			//---------------------------------RECEIVING HEADER FROM THE SENDER--------------------------//

			if ((numbytes = read(newfd, &HelloReceived1[0], 1))==-1)
			{
				//	perror("read3");
					exit(1);
			}

			//-------------------------------RECEIVING HEADER FROM THE SENDER END---------------------------------//

			//-------------------------------COPYING RECEIVED HEADER ONTO LOCAL STRUCTURE-----------------------------//
			helloRecvd1.UOID = new unsigned char[20];
			memcpy(&helloRecvd1.MessageType,&HelloReceived1[0],1);

			if (helloRecvd1.MessageType == HLLO)
			{
				for (unsigned int it6 = 1;it6<27 ;it6++ )
				{
					if ((numbytes = read(newfd, &HelloReceived1[it6], 1))==-1)
					{
					//	perror("read4");
						exit(1);
					}
				}
			/*	for(int it2=0;it2<20;it2++){
					printf("%02x",(unsigned char)UOIDstr[it2]);
				}cout<<endl;
	*/
				memcpy(helloRecvd1.UOID,&HelloReceived1[1],20);
				memcpy(&helloRecvd1.TTL,&HelloReceived1[21],1);
				memcpy(&helloRecvd1.Reserved,&HelloReceived1[22],1);
				memcpy(&helloRecvd1.DataLength,&HelloReceived1[23],4);
		//		cout<<"UUUUUUUUUUUUUUUUOOOOOOOOOOOOOOOOOOOOIIIIIIIIIIIIIIIIIIIIIIIIIDDDDDDDDDDDDDDDDDDDDDD"<<endl;



				for(int it2=0;it2<20;it2++){
	//				printf("%02x",(unsigned char)helloRecvd1.UOID[it2]);
				}
		//		cout<<endl;

				//-------------------------------COPYING RECEIVED HEADER ONTO LOCAL STRUCTURE END-----------------------------//

				//--------------------------------------RECEIVING MSG FROM THE SENDER-------------------------------------//
				for (unsigned int it3 = 27;it3<27+helloRecvd1.DataLength ;it3++ )
				{
					if ((numbytes = read(newfd, &HelloReceived1[it3], 1))==-1)
					{
						//perror("read5");
						exit(1);
					}
				}
				//--------------------------------------RECEIVING MSG FROM THE SENDER END-------------------------------------//


				memcpy(&RecvdMsg1.HostPort,&HelloReceived1[27],2);
				memcpy(&RecvdMsg1.HostName,&HelloReceived1[29],helloRecvd1.DataLength-2);
		//		cout<<"Host port received on accept "<<RecvdMsg1.HostPort<<endl;



				//---------------------------------------------- RESET----------------------------------------------------//
				pthread_mutex_lock(&log_lock);
				FILE *Log = fopen(LogLocation.c_str(),"a");
				if(Log==NULL)
				{
					cerr<<"Log file can not be opened. The program will continue without logging."<<endl;
				}else{
				if (i1->Port != RecvdMsg1.HostPort){

				gettimeofday(&tim,NULL);
				fprintf(Log,"r %10ld.%03d nunki.usc.edu_%d HLLO %d ",(tim.tv_sec),(int)((tim.tv_usec)/1000),RecvdMsg1.HostPort,(int)(helloRecvd1.TTL));
				for(int pr=16;pr<20;pr++){fprintf(Log,"%02x",helloRecvd1.UOID[pr]);}
				fprintf(Log," %d nunki.usc.edu\n",RecvdMsg1.HostPort);
				fflush(Log);
				}
				}
				fclose(Log);
				pthread_mutex_unlock(&log_lock);
				//---------------------------------------------------------------------------------------------------------//

				//--------------------------CHECKING FOR DUPLICATE CONNECTIONS BEGIN--------------------------------------//

				if (RecvdMsg1.HostPort <= i1->Port)
				{
					for (it=i1->BeaconList.begin(); it!=i1->BeaconList.end(); it++)
					{
						if (RecvdMsg1.HostPort == (*it).BeaconPort)
						{
							checkFlag=1;
		//					cout<<"Closing child accept on port "<<i1->Port<<endl;
							close(newfd);
						}
					}

				list<GlobalList_Elem*>::iterator globalit;
				for (globalit = GlobalList.begin();globalit!=GlobalList.end();globalit++)
				{
					GlobalList_Elem* g1 = new GlobalList_Elem();
					g1 = (GlobalList_Elem*) (*globalit);
					if (g1->Port == RecvdMsg1.HostPort)
					{
		//				cout<<"Duplicate connection: "<<g1->Port<<endl;
			//			GlobalList.remove(*globalit);
						close(newfd);
						checkFlag = 1;
					}
				}
				}
				//else{
				if (checkFlag==0)
				{

				//----------------------------------------------- BUILD ELEM FOR NEIGHBOR LIST -------------------------------//
		//		cout<<"About to append on beacon server : "<<RecvdMsg1.HostPort<<endl;
				NeighborList_Elem* elem = new NeighborList_Elem();
				elem->UOID = new unsigned char[20];
				memcpy(elem->UOID,&HelloReceived1[1],20);
				memcpy(&(elem->HostPort),&HelloReceived1[27],2);

				//----------------------------------------------BUILD ELEM FOR NEIGHBOR LIST END CHECKED AND WORKING----------------------//

				//------------------------------ APPENDING NEIGHBORS FOR DUPLICATES BEGIN -------------------------------------//


				//ACQUIRE A LOCK ON THE NEIGHBOR LIST AND APPEND THE NEIGHBOR INTO THE LIST
				pthread_mutex_lock(&NeighborList_lock);
		//		for(int it2=0;it2<20;it2++){printf("%02x",(unsigned char)(elem->UOID)[it2]);}
				//cout<<endl;cout<<elem->HostPort<<endl;
				NeighborList->Append((void *)elem);
			//	print_NeighborList();
				My570ListElem* curr = new My570ListElem();

				curr=NeighborList->First();
				for(int iter=0;iter<20;iter++){}
			//	printf("%02x",(unsigned char)(((NeighborList_Elem*)(curr->Obj()))->UOID)[iter]);}
				//cout<<endl;
				//cout<<"Printed the list UOID-----------------------"<<endl;

				Duplicate = eval_Duplicate();
				//print_NeighborList();
				if (Duplicate == 0)
				{
					//cout<<"Duplicate found on server."<<endl;
				}
				pthread_mutex_unlock(&NeighborList_lock);
				//------------------------------ APPENDING NEIGHBORS FOR DUPLICATES END ---------------------------------------//
				GlobalList_Elem *Gelem = new GlobalList_Elem();
				list<Flood_Elem*>* EventQ = new list<Flood_Elem*>;
				Gelem->UOID = new unsigned char[20];
				Gelem->ListP = *EventQ;
				Gelem->Port =  RecvdMsg1.HostPort;
				Gelem->Temp = 0;
				Gelem->Socket=newfd;
				memcpy(Gelem->UOID,&HelloReceived1[1],20);
				pthread_mutex_lock(&GlobalList_lock);
				GlobalList.push_back(Gelem);
				dupGlobal = eval_Global1();
			//	print_GlobalList();
				pthread_mutex_unlock(&GlobalList_lock);

				//----------------------------------RESPONSE HELLLO MESSAGE CREATION---------------------------//
				struct HEADER hello1;
				struct HELLO_MSG msg1;

				hello1.UOID = new unsigned char[20];
				hello1.MessageType=HLLO;
				for(int it2=0;it2<20;it2++){
					hello1.UOID[it2]=(GetUOID(node_instance_id,"msg"))[it2];
				}

				int i=30;
				if(i1->TTL==0){hello1.TTL=(unsigned char)i;}else{hello1.TTL=(unsigned char)i1->TTL;}
				hello1.Reserved=(unsigned char)0;
				msg1.HostPort=i1->Port;
				msg1.HostName=hostname;
				hello1.DataLength=(int)strlen(msg1.HostName)+2;

				unsigned char* HelloMessage1 = new unsigned char[512];
				memset(HelloMessage1,'\0',512);
				memcpy(&HelloMessage1[0],&hello1.MessageType,1);
	/*			for(int it2=0;it2<20;it2++){
					printf("%02x",(unsigned char)UOIDstr[it2]);
				}cout<<endl;
	*/
				memcpy(&HelloMessage1[1],hello1.UOID,20);
				memcpy(&HelloMessage1[21],&hello1.TTL,1);
				memcpy(&HelloMessage1[22],&hello1.Reserved,1);
				memcpy(&HelloMessage1[23],&hello1.DataLength,4);
				memcpy(&HelloMessage1[27],&msg1.HostPort,2);
				memcpy(&HelloMessage1[29],&msg1.HostName,strlen(msg1.HostName));


				//cout<<"Sending message from "<<i1->Port<<" to"<<ntohs(peer.sin_port)<<endl;
					////////SENDING RESPONSE HELLO MESSAGE BACK///////////
					for (unsigned int it4 = 0;it4<27 ;it4++ )
					{
						if (send(newfd,&HelloMessage1[it4],1,0)==-1)
						{
						//	perror("beaconconnect3: write");
							exit(1);
						}
					}
					for (unsigned int it5 = 27;it5<27+hello1.DataLength; it5++ )
					{
						if (send(newfd,&HelloMessage1[it5],1,0)==-1)
						{
							//perror("beaconconnect4: write");
							exit(1);
						}
					}
						//cout<<"Message sent from "<<serv_addr.sin_port<<endl;
					//cout<<"UUUUUUUUUUUUUUUUOOOOOOOOOOOOOOOOOOOOIIIIIIIIIIIIIIIIIIIIIIIIIDDDDDDDDDDDDDDDDDDDDDD"<<endl;
					for(int it2=0;it2<20;it2++){
			//			printf("%02x",(unsigned char)hello1.UOID[it2]);
					}

					//---------------------------------------------- RESET----------------------------------------------------//
				pthread_mutex_lock(&log_lock);
				FILE *Log = fopen(LogLocation.c_str(),"a");
				if(Log==NULL)
				{
					cerr<<"Log file can not be opened. The program will continue without logging."<<endl;
				}else{
				if (i1->Port != RecvdMsg1.HostPort){
				gettimeofday(&tim,NULL);
				fprintf(Log,"s %10ld.%03d nunki.usc.edu_%d HLLO %d ",(tim.tv_sec),(int)((tim.tv_usec)/1000),ntohs(peer.sin_port),(int)(helloRecvd1.TTL));
				for(int pr=16;pr<20;pr++){fprintf(Log,"%02x",hello1.UOID[pr]);}
				fprintf(Log," %d nunki.usc.edu\n",msg1.HostPort);
				fflush(Log);
				}
				}
				fclose(Log);
				pthread_mutex_unlock(&log_lock);
				//---------------------------------------------------------------------------------------------------------//


						//------------------------------SENDING RESPONSE HELLO MSG END-----------------------------------//

						pthread_mutex_lock(&SocketList_lock);
						SocketList->Append((void*)newfd);
						pthread_mutex_unlock(&SocketList_lock);
						//------------------------------------
						//My570List *EventQ = new My570List();
						//------------------------------------

						//cout<<"newfd1 "<<newfd<<" connected to "<<RecvdMsg1.HostPort<<endl;
						if ((ret = pthread_create(&readt,NULL,readthread,(void *)Gelem)))
						{
							//error has occurred
							fprintf(stderr,"Error:pthread_create, %s\n",strerror(ret));
							exit(1);
						}
						//cout<<"newfd2 "<<newfd<<" connected to "<<RecvdMsg1.HostPort<<endl;
						if ((ret = pthread_create(&writet,NULL,writethread,(void *)Gelem)))
						{
							//error has occurred
							fprintf(stderr,"Error:pthread_create, %s\n",strerror(ret));
							exit(1);
						}

					}//end if duplicate condition
			}//end if messagetype hello
			else{
				//int Rdbytes = 19
				 if(helloRecvd1.MessageType == JNRQ){

                    //cout<<"Before creating process thread______________________________________"<<endl;
					int thrd_Process=0;
					pthread_t Process_thread;
                    thrd_Process=pthread_create(&Process_thread,&attr,Process_func,(void*)newfd);
					if(thrd_Process){
						cerr<<"Error; return code from thread KeepAlive create call is"<<thrd_Process<<endl;
						exit(-1);
					}

			}//if messagetype = JNRQ

			//cout<<"NonBeacon Node"<<endl;


			}//end else if messagetype != HLLO
		}//end else accept
	}//end while

	close(sockfd);
	close(newsock);
//	pthread_kill(Keyboard_thread,SIGUSR1);

	//cout<<"breaking server"<<endl;
	return 0;
}


int main(int argc, char** argv)
{
	AutoShutDown=0;
	//____________________________________________________- SIGNALS -_____________________________________//
    //BLOCKING
	sigemptyset(&sigalrm);
	sigaddset(&sigalrm, SIGALRM);
	pthread_sigmask(SIG_BLOCK, &sigalrm, NULL);

    sigemptyset(&sigint);
    sigaddset(&sigint, SIGINT);
    pthread_sigmask(SIG_BLOCK, &sigint, NULL);

	sigemptyset(&sigpipe);
	sigaddset(&sigpipe,SIGPIPE);
	pthread_sigmask(SIG_BLOCK, &sigpipe, NULL);

	//signal(SIGSEGV, my_segment_handler);

   //____________________________________________________- SIGNALS -_____________________________________//

	// command line parser
    string s1="-reset";
	const char* filename;
	int resetflag=0;

	if(argc<2 || argc>3)
	{
		cerr<<"Malformed command line. The program will exit now."<<endl;
		exit(1);
	}

	int arco=1;
	while(argv[arco]!=NULL)
	{
		string argument=string(argv[arco]);

		if(argument.compare(s1)==0){
//			cout<<"RESETFLAG"<<endl;
			resetflag=1;
			arco=arco+1;
		}else{
            filename = argv[arco];
			arco=arco+1;
		}

	}

	//----------------INIITIALIZE SYNCHRONIZATION VARIABLES BEGIN---------------------------------------------//

	pthread_mutex_init(&NeighborList_lock,NULL);
	pthread_mutex_init(&SocketList_lock,NULL);
	pthread_mutex_init(&EventQ_lock,NULL);
	pthread_mutex_init(&GlobalList_lock,NULL);
	pthread_mutex_init(&PrintLock,NULL);
	pthread_mutex_init(&DBaseLock,NULL);
	pthread_mutex_init(&status_lock,NULL);
	pthread_cond_init(&EventQ_cv,NULL);
	pthread_mutex_init(&log_lock,NULL);

//	sigemptyset(&sigpipe);
//	sigaddset(&sigpipe, SIGPIPE);

   //----------------INIITIALIZE SYNCHRONIZATION VARIABLES END------------------------------------------------//

    //----------------FILE PARSING BEGIN----------------------------------------------------------------------//

	i1=ini_parser(filename);

    //----------------FILE PARSING END-----------------------------------------------------------------------//
	list<beacon> mybeaconlist;
	int BeaconFlag = 0;

	for (it=i1->BeaconList.begin(); it!=i1->BeaconList.end(); it++)
	{
		//cout<<(*it).BeaconPort<<endl;
		//cout<<"+++++++"<<endl;
		//cout<<(*it).BeaconName<<endl;
		if (i1->Port == (*it).BeaconPort)
		{
			BeaconFlag = 1;
		}
	}
	noofbeacons = i1->BeaconList.size();
	//cout<<"noofbeacons: "<<noofbeacons<<endl;


	//---------------------LOG FILE NAME GENERATION AND OPEN BEGIN------------------------------------------//

    LogLocation = (string(HomeDir1)).substr(0,(int)strlen(HomeDir1)-1);
	string InitLocation1;
	if(LogFilename1==NULL){
		InitLocation1= LogLocation + "/init_neighbor_list";
		LogLocation = LogLocation + "/servant.log";
	}else{
		InitLocation1= LogLocation + "/init_neighbor_list";
		string LogTerminal = (string(LogFilename1)).substr(0,(int)strlen(LogFilename1)-1);
		LogLocation = LogLocation + LogTerminal;
	}
	//cout<<"Logfile address "<<LogLocation<<endl;//exit(1);


	//--------------------LOG FILE NAME GENERATION AND OPEN END-------------------------------------------//

	//----------------RESET-----------------------------------------------------------------------------------//
	if(resetflag==1){
		if(remove(LogLocation.c_str())!=0){
          cerr<<"Log File not Found"<<endl;
		}
		if(remove(InitLocation1.c_str())!=0){
			cerr<<"Init File not Found"<<endl;
		}
	}

	//---------------------------------------------- RESET----------------------------------------------------//
    pthread_mutex_lock(&log_lock);
	FILE *Log = fopen(LogLocation.c_str(),"a");
	if(Log==NULL)
	{
		cerr<<"Log file can not be opened. The program will continue without logging."<<endl;
	}else{
		gettimeofday(&tim,NULL);
		fprintf(Log,"// %10ld.%03d nunki.usc.edu_%d \n",(tim.tv_sec),(int)((tim.tv_usec)/1000),i1->Port);
	}
	fclose(Log);
	pthread_mutex_unlock(&log_lock);
	//---------------------------------------------------------------------------------------------------------//
	gethostname(hostname, sizeof hostname);
	//cout<<"creating the socket: \n";
	if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
	{
	//	perror("Socket");
		exit(1);
	}
	//cout<<"Socket "<<sockfd<<" created.\n";

	//------------------CREATING THE UOID, GETTING THE HOSTNAME, PORT AND TIME BEGIN---------------------------//
	int hostport = 0;
	time_t nodetime;
	hostport = i1->Port;
	//cout<<"Hostname: "<<hostname<<endl;
	//cout<<"Port: "<<hostport<<endl;
	nodetime = time(NULL);
	//cout<<"Time : "<<nodetime<<endl;

//	unsigned char *node_instance_id = new unsigned char[512];
	node_instance_id = Get_node_inst_id(hostname,hostport,nodetime);
	//cout<<node_instance_id<<endl;

	unsigned char* printme = new unsigned char[20];
	printme	= GetUOID(node_instance_id,"msg");

/*	for(int k=0;k<20;k++)
	{
		printf("%02x",(unsigned char)printme[k]);
	}
*/
	//memcpy(UOIDstr,&printme,20);

	for(int it2=0;it2<20;it2++){
		UOIDstr[it2]=printme[it2];
//		printf("%02x",(unsigned char)UOIDstr[it2]);
	}

   //------------------CREATING THE UOID, GETTING THE HOSTNAME, PORT AND TIME END---------------------------//
   int time_seconds =0;

   if(i1->AutoShutdown == 0){
	   time_seconds=900;
   }else{
	   time_seconds=i1->AutoShutdown;
   }

   alarm(time_seconds);

   //------------------PTHREADS CREATE BEGIN----------------------------------------------------------------//

	int thrd_KeepAlive;
	int thrd_Keyboard;
	int thrd_server;
	int thrd_beaconconnect;
	int thrd_join;

	pthread_t server,beaconconnect;
	//pthread_t KeepAlive_thread;
	//pthread_t Keyboard_thread;
	pthread_t Join_thread;

	pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	void *status_KA;


//	pthread_sigmask(SIG_BLOCK, &sigpipe, NULL);

	if (BeaconFlag == 1)
	{
		thrd_server=pthread_create(&server,&attr,serverthread,(void*)sockfd);
		if(thrd_server){
			cerr<<"Error; return code from thread Server create call is"<<thrd_server<<endl;
			exit(-1);
		}

		thrd_beaconconnect=pthread_create(&beaconconnect,&attr,beaconconnectthread,(void*)noofbeacons);
		if(thrd_beaconconnect){
			cerr<<"Error; return code from thread BeaconConnect create call is"<<thrd_beaconconnect<<endl;
			exit(-1);
		}
	}else{
		//cout<<"Encountered Non Beacon Node, shifting control to sending join message"<<endl;
		thrd_join = pthread_create(&Join_thread,&attr,NonBeacon_Join,(void*)sockfd);
		if(thrd_join){
			cerr<<"Error; return code from thread Server create call is"<<thrd_server<<endl;
			exit(-1);
		}

	}
	thrd_KeepAlive=pthread_create(&KeepAlive_thread,&attr,KeepAlive_func,NULL);
    if(thrd_KeepAlive){
		cerr<<"Error; return code from thread KeepAlive create call is"<<thrd_KeepAlive<<endl;
		exit(-1);
	}
	thrd_Keyboard=pthread_create(&Keyboard_thread,&attr,Keyboard_func,NULL);
	if(thrd_Keyboard){
		cerr<<"Error; return code from thread Keyboard create call is "<<thrd_Keyboard<<endl;
		exit(-1);
	}

	if (BeaconFlag!=1)
	{
	thrd_join=pthread_join(Join_thread,&status_KA);
	if(thrd_join){
		cerr<<"Error; return code from thread Join join call is "<<thrd_join<<endl;
		exit(-1);
	}

	}
	else{
				thrd_server=pthread_join(server,&status_KA);
		if(thrd_server){
			cerr<<"Error; return code from thread Server join call is "<<thrd_server<<endl;
			exit(-1);
		}
			thrd_beaconconnect=pthread_join(beaconconnect,&status_KA);
	if(thrd_beaconconnect){
		cerr<<"Error; return code from thread Connect join call is "<<thrd_beaconconnect<<endl;
		exit(-1);
	}
	}
    KeepAliveExit=1;
	thrd_KeepAlive=pthread_join(KeepAlive_thread,&status_KA);
	if(thrd_KeepAlive){
		cerr<<"Error; return code from thread KeepAlive join call is "<<thrd_KeepAlive<<endl;
		exit(-1);
	}
	thrd_Keyboard=pthread_join(Keyboard_thread,&status_KA);
	if(thrd_Keyboard){
		cerr<<"Error; return code from thread Keyboard join call is "<<thrd_Keyboard<<endl;
		exit(-1);
	}


   //------------------PTHREADS CREATE END----------------------------------------------------------------//


    close(sockfd);
	fclose(Log);

	//----------------CLEAN UP BEGIN---------------------------------------------------------------------//
	pthread_cond_destroy(&EventQ_cv);
	pthread_mutex_destroy(&NeighborList_lock);
	pthread_mutex_destroy(&SocketList_lock);
	pthread_mutex_destroy(&EventQ_lock);
	pthread_mutex_destroy(&GlobalList_lock);
	pthread_mutex_destroy(&log_lock);

	killSocketList();
	//----------------CLEAN UP END-----------------------------------------------------------------------//
	return 0;
}



